package com.ooo.ttt.opencvlib;

import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import androidx.annotation.NonNull;

public class FaceDector {
    private HandlerThread mHandlerThread;
    private Handler mHandler;

    private Handler mUiHandler;


    private static class MyHandler extends Handler {
        public OnNativeFaceResult result;

        public MyHandler(OnNativeFaceResult result) {
            super(Looper.myLooper());
            this.result = result;
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what == MISSION_ID_2) {
                NativeFace[] nativeFaces = (NativeFace[]) msg.obj;
                if (result != null) {
                    result.onResult(nativeFaces);
                }
            }

        }
    }

    private static final int MISSION_ID_2 = 12;
    private static final int MISSION_ID = 11;

    private int width = 800;
    private int height = 400;
    private long mNativeObj = 0;


    static {
        System.loadLibrary("face-lib");
    }

    public FaceDector(String cascadeName, int minFaceSize, OnNativeFaceResult result) {
        mNativeObj = nativeCreateObject(cascadeName, minFaceSize);

        mUiHandler = new MyHandler(result);

        mHandlerThread = new HandlerThread("FaceTrack");
        mHandlerThread.start();

        mHandler = new Handler(mHandlerThread.getLooper()) {
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);

                synchronized (FaceDector.this) {
                    int width = msg.arg1;
                    int height = msg.arg2;
                    byte[] bytes = (byte[]) msg.obj;

                    NativeFace[] nativeFaces = nativeDetect(mNativeObj, bytes, width, height);

                    if (nativeFaces != null && nativeFaces.length > 0 && mUiHandler != null) {
                        Message message = mUiHandler.obtainMessage();
                        message.obj = nativeFaces;
                        message.what = MISSION_ID_2;
                        mUiHandler.sendMessage(message);
                    }
                }

            }
        };
    }

    public boolean isMainThread() {
        return Looper.getMainLooper() == Looper.myLooper();
    }

    public interface OnNativeFaceResult {
        void onResult(NativeFace[] nativeFaces);
    }


    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }


    public void start() {
        nativeStart(mNativeObj);
    }

    public void stop() {
        synchronized (FaceDector.this) {
            if (Build.VERSION.SDK_INT >= 18) {
                mHandlerThread.quitSafely();
            } else {
                mHandlerThread.quit();
            }
            mHandler.removeCallbacksAndMessages(null);
            nativeStop(mNativeObj);
            mNativeObj = 0;
            mUiHandler.removeMessages(MISSION_ID_2);
        }

    }

    // byte[] data == NV21 Camera的数据 byte[]
    public void detector(byte[] data, int width, int height, int degree) { // 要把相机的数据，给C++层做人脸追踪
        // 把积压的 11号任务移除掉
        mHandler.removeMessages(MISSION_ID);
        // 加入新的11号任务
        Message message = mHandler.obtainMessage(MISSION_ID);
        message.obj = data;

        message.arg1 = width;
        message.arg2 = height;
        mHandler.sendMessage(message);
        setNativeDegree(degree);

    }


    public void release() {
        nativeStop(mNativeObj);
        mNativeObj = 0;
    }


    public void setCameraId(int cameraId) {
        setNativeCameraId(cameraId);
    }

    private static native long nativeCreateObject(String cascadeName, int minFaceSize);


    private static native void nativeStart(long detector);

    private static native void nativeStop(long detector);

    private static native void setNativeDegree(int degree);

    private static native void setNativeCameraId(int cameraId);


    private static native NativeFace[] nativeDetect(long detector, byte[] inputImage, int width, int height);
}
